#include "model/der/Entity.h"
#include <iostream>
#include <string>
#include <sstream>
#include <typeinfo>
#include "gui/Dibujar/Defines.h"
#include "model/Connector.h"
#include "model/der/ViaDER.h"
#include "model/der/Attribute.h"

Entity::Entity(const std::string & name, int orientation)
	: ComponentDER(name, orientation)
{
	initializeConnectors();
}


Entity::Entity(const Entity & otro) : ComponentDER(otro){

	initializeConnectors();
}


Entity& Entity::operator=(const Entity& otro) {

	ComponentDER::operator=(otro);
	initializeConnectors();
	return *this;
}

void Entity::initializeConnectors() {
	componentType = ComponentTypeDerEntity;

	addConnector(ENTITY_ENTRADA_0, true, 0, 1);
	addConnector(ENTITY_ENTRADA_1, true, 0, 2);
	addConnector(ENTITY_ENTRADA_2, true, 0, 3);
	addConnector(ENTITY_ENTRADA_3, true, 0, 4);
	addConnector(ENTITY_ENTRADA_4, true, 0, 5);
	addConnector(ENTITY_ENTRADA_5, true, 0, 6);
	addConnector(ENTITY_ENTRADA_6, true, 0, 7);
	addConnector(ENTITY_ENTRADA_7, true, 0, 8);
	addConnector(ENTITY_ENTRADA_8, true, 0, 9);
	addConnector(ENTITY_ENTRADA_9, true, 0, 10);
	addConnector(ENTITY_ENTRADA_10, true, 0, 11);
	addConnector(ENTITY_ENTRADA_11, true, 0, 12);
	addConnector(ENTITY_ENTRADA_12, true, 0, 13);
	addConnector(ENTITY_ENTRADA_13, true, 0, 14);
	addConnector(ENTITY_ENTRADA_14, true, 0, 15);
	addConnector(ENTITY_ENTRADA_15, true, 0, 16);
	addConnector(ENTITY_ENTRADA_16, true, 0, 17);
	addConnector(ENTITY_ENTRADA_17, true, 0, 18);
	addConnector(ENTITY_ENTRADA_18, true, 0, 19);
	addConnector(ENTITY_ENTRADA_19, true, 0, 20);
	addConnector(ENTITY_ENTRADA_20, true, 0, 21);
	addConnector(ENTITY_ENTRADA_21, true, 0, 22);
	addConnector(ENTITY_ENTRADA_22, true, 0, 23);
	addConnector(ENTITY_ENTRADA_23, true, 0, 24);
	addConnector(ENTITY_ENTRADA_24, true, 0, 25);
	addConnector(ENTITY_ENTRADA_25, true, 0, 26);
	addConnector(ENTITY_ENTRADA_26, true, 0, 27);
	addConnector(ENTITY_ENTRADA_27, true, 0, 28);
	addConnector(ENTITY_ENTRADA_28, true, 0, 29);


	m_types.push_back("Fuerte");
	m_types.push_back("Debil");
	m_types.push_back("Transaccional");
	m_types.push_back("Maestra");
}

void Entity::serialize(XmlWriter & writer_rep, XmlWriter & writer_comp)
{
	writer_rep.addRootChild(TARGET_ENTITY, "");
	ComponentDER::serialize(writer_rep, writer_comp);
}

void Entity::update()
{
	m_attributes.clear();
	m_entityAttributes.clear();
	m_entityCompositeAttributes.clear();
	m_componentesYConectores.clear();

	for(unsigned i = 0; i < conectoresEntrantes.size(); i++){
		if(conectoresEntrantes[i]->getVia() != NULL) {
			Via* via = conectoresEntrantes[i]->getVia();

			Component *c = NULL;
			if(via->getEndConnector() != conectoresEntrantes[i]) {
				c = via->getEndConnector()->getFather();
				m_attributes.push_back(dynamic_cast<Attribute*>(c));
				m_componentesYConectores.insert(std::pair<Component *, Connector *>(c, conectoresEntrantes[i]));
			} else {
				c = via->getStartConnector()->getFather();
				m_attributes.push_back(dynamic_cast<Attribute*>(c));
				m_componentesYConectores.insert(std::pair<Component *, Connector *>(c, conectoresEntrantes[i]));
			}

			switch (c->getComponentType()) {
				case ComponentTypeDerCompositeAttribute:
					m_entityCompositeAttributes.push_back(dynamic_cast<CompositeAttribute *>(c));
					break;
				case ComponentTypeDerAttribute:
					m_entityAttributes.push_back(dynamic_cast<Attribute *>(c));
					break;
				default:
					break;
			}
		}
	}
}

std::vector<Attribute *> Entity::getEntityAttributes() {
	this->update();
	return m_entityAttributes;
}

std::vector<CompositeAttribute *> Entity::getEntityCompositeAttributes() {
	this->update();
	return m_entityCompositeAttributes;
}

std::string Entity::description() {
	this->update();

	std::string d = "";
	d += "ENTIDAD: " + this->getName() + " ( \n";
	for (unsigned int i = 0; i < m_entityAttributes.size(); i++) {
		Attribute *a = m_entityAttributes[i];
		d += "  " + a->description() + ",\n";
	}
	for (unsigned int i = 0; i < m_entityCompositeAttributes.size(); i++) {
		CompositeAttribute *a = m_entityCompositeAttributes[i];
		d += "  " + a->description() + ",\n";
	}
	d += ")\n";
	return d;
}

